package com.itheima.app.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.itheima.app.exception.BusinessException;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.face.AipFaceTemplate;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.autoconfig.sms.SmsTemplate;
import com.itheima.domain.db.*;
import com.itheima.service.db.NotificationService;
import com.itheima.service.db.QuestionService;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.db.UserService;
import com.itheima.utils.ConstantUtil;
import com.itheima.utils.JwtUtil;
import com.itheima.vo.SettingVo;
import com.itheima.vo.UserInfoVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.tomcat.util.bcel.Const;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Guanxing
 * @date 2021/9/18
 */
@Component
public class UserManager {

    @Reference
    private UserService userService;

    @Autowired
    private SmsTemplate smsTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Reference
    private UserInfoService userInfoService;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private AipFaceTemplate aipFaceTemplate;

    @Reference
    private QuestionService questionService;

    @Reference
    private NotificationService notificationService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    //添加用户
    public Long save(User user) {
        //加密处理
        String md5Pwd = SecureUtil.md5(user.getPassword());
        user.setPassword(md5Pwd);

        //保存对象
        Long id = userService.save(user);

        return id;
    }

    //根据手机号查询用户
    public User findByPhone(String phone) {
        return userService.findByPhone(phone);
    }

    //发送验证码
    public void sendSms(String phone) {
        //生成随机验证码
        //int code = RandomUtil.randomInt(6);
        //发送验证码
        //smsTemplate.sendSms(phone,String.valueOf(code));

        //保存到redis,超时5分钟
        stringRedisTemplate.opsForValue().set(ConstantUtil.SMS_CODE + phone, "123456", Duration.ofMinutes(5));
    }

    //登录或者注册
    public Map regOrLog(String phone, String verificationCode) {
        //从redis中获取验证码
        String code = stringRedisTemplate.opsForValue().get(ConstantUtil.SMS_CODE + phone);
        //对比验证码
        if (!StrUtil.equals(verificationCode, code)) {
            //对比失败抛出异常
            throw new RuntimeException("验证码输入错误");
        }

        //删除redis中的验证码
        stringRedisTemplate.delete(ConstantUtil.SMS_CODE + phone);

        //创建log
        Log log = new Log();

        //对比成功,根据手机号查询用户
        User user = userService.findByPhone(phone);
        Boolean flag = false;
        //如果查询不到,进行注册
        if (user == null) {
            user = new User();
            user.setPhone(phone);
            user.setPassword(ConstantUtil.INIT_PASSWORD);
            Long id = save(user);
            user.setId(id); //赋值id的目的是:后续代码需要构建token使用
            System.out.println("注册后的用户对象是:" + user);
            flag = true;//执行注册标志
            log.setType("0102");
        } else {
            //如果查询到用户,执行登录
            flag = false;
            log.setType("0101"); //0101为登录
        }

        log.setUserId(user.getId());

        rocketMQTemplate.convertAndSend("tanhua-log", log);

        //登录或者注册后,将数据存入redis
        //转换成token
        Map<String, Object> map = new HashMap<>();
        map.put("id", user.getId());
        map.put("phone", phone);
        String token = JwtUtil.createToken(map);
        //存入token主要是存入用户的登录状态 (所有的登陆信息 在token中)
        stringRedisTemplate.opsForValue().set(ConstantUtil.USER_TOKEN + token,
                "1", Duration.ofMinutes(7));
        //构建返回数据
        Map returnMap = new HashMap();
        returnMap.put("token", token);
        returnMap.put("isNew", flag);
        return returnMap;
    }

    //保存用户基础信息
    public void saveUserInfo(UserInfo userInfo) {
        //暂时写死一些数据 因为前段没有传入
        userInfo.setTags("单身,本科,年龄相仿"); //这个是必须给的
        userInfo.setAge(18);
        userInfo.setProfession("计算机");
        userInfo.setIncome("30");
        userInfo.setMarriage(1);

        //保存用户基础信息
        userInfoService.save(userInfo);
    }

    //保存用户对象
    public void updateUserInfo(MultipartFile headPhoto, Long id) throws IOException {
        //百度云人脸识别
        boolean flag = aipFaceTemplate.detect(headPhoto.getBytes());
        if (flag) {
            //人脸的情况下
            //2.文件上传
            String uploadPath = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());
            //3.正常保存到数据库即可
            UserInfo userInfo = new UserInfo();
            userInfo.setId(id); //赋值id
            userInfo.setCoverPic("https://" + uploadPath); //朋友圈封面
            userInfo.setAvatar("https://" + uploadPath);//头像
            userInfoService.update(userInfo);//修改头像
        }
    }

    //根据用户的id查询用户的信息
    public UserInfoVo findByUserId(Long userId) {
        //查询数据库的实体数据
        UserInfo userInfo = userInfoService.findById(userId);

        //创建前端所需要的对象
        UserInfoVo userInfoVo = new UserInfoVo();
        //数据转移
        BeanUtil.copyProperties(userInfo, userInfoVo);

        //特殊设置
        userInfoVo.setAge(userInfo.getAge().toString());

        return userInfoVo;
    }

    //修改用户的个人信息
    public void updateUserInfo(UserInfo userInfo) {
        userInfoService.update(userInfo);
    }

    //修改手机号 - 2 校验验证码
    public Map checkVerificationCode(String verificationCode) {
        //2.从redis中获取验证码
        String code = stringRedisTemplate.opsForValue().get(ConstantUtil.SMS_CODE + UserHolder.get().getPhone());
        //3.比对验证码
        boolean verification = StrUtil.equals(verificationCode, code);
        //4.创建map
        Map map = new HashMap();
        map.put("verification", verification);
        return map;
    }

    //修改手机号 - 3 保存
    public void updatePhone(String phone) throws BusinessException {
        //1.判断手机号是否为11位
        if (phone.length() == 11) {
            //2.判断手机号是否已存在
            User userByPhone = userService.findByPhone(phone);
            if (userByPhone == null) {
                //3.获取当前user对象
                User user = UserHolder.get();
                //4.设置手机号
                user.setPhone(phone);
                //5.保存修改
                userService.updatePhone(user);
            } else {
                throw new BusinessException("此手机号已被注册！");
            }
        } else {
            throw new BusinessException("手机号不是11位");
        }

    }

    //3.删除原账号token
    public void deleteToken(String token) {
        stringRedisTemplate.delete(ConstantUtil.USER_TOKEN + token);
    }

}
